package demo;

import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.CountDownLatch;

public class MatrixMulti extends Thread{
	private double[][] A;
	private double[][] B;
	private int index;
	private int gap;
	private double[][] result;
	private CountDownLatch countDownLatch;
 
	 public MatrixMulti(double[][] A, double[][] B, int index, int gap, double[][] result, CountDownLatch countDownLatch) {
		this.A = A;
		this.B = B;
		this.index = index;
		this.gap = gap;
		this.result = result;
		this.countDownLatch = countDownLatch;
	}
 
	// 计算特定范围内的结果
	public void run() {
		// TODO Auto-generated method stub
		for (int i = index * gap; i < (index + 1) * gap; i++)
			for (int j = 0; j < B[0].length; j++) {
				for (int k = 0; k < B.length; k++)
					result[i][j] += A[i][k] * B[k][j];
			}
		// 线程数减1
		countDownLatch.countDown();
	}
	
	public static void print(double[][] a) {
		for (int j = 0; j < a[0].length; j++) {
			for (int k = 0; k < a.length; k++) {
				System.out.print(a[j][k] + " ");
			}
			System.out.println();
		}
	}
 
	//二维矩阵比较
	public static boolean diffDoubleSecondArr(double[][] paramDouble,double[][] diffDouble){
        List<Double> ResultList = new ArrayList<>();
        List<Double> DiffList = new ArrayList<>();
        for(double[] npdArr : paramDouble){
            for(double children : npdArr){
                ResultList.add(children);
            }
        }
        for(double[] dpdArr : diffDouble){
            for(double children : dpdArr){
                DiffList.add(children);
            }
        }
        //如果两个长度不相等
        if(ResultList.size()!=DiffList.size()){
            return false;
        }
        for(int i = 0;i<ResultList.size();i++){
            if(!ResultList.get(i).equals(DiffList.get(i))){
                return false;
            }
        }
        return true;
    }

	public static void main(String[] args) throws InterruptedException {
		// 声明和初始化
		MatrixGenerator matrixA = new MatrixGenerator();
		MatrixGenerator matrixB = new MatrixGenerator();
		long startTime;
		long endTime;
		int row_A = 500;
		int col_A = 500;
		int col_B = 500;
		double[][] A = matrixA.create_Matrix(row_A,col_A); 
				//[row_A][col_A];
		double[][] B = matrixB.create_Matrix(col_A,col_B);
			
        //存放并行计算结果
		double[][] parallel_result = new double[A.length][B[0].length];
        //存放串行计算结果
		double[][] serial_result = new double[A.length][B[0].length];
        //子线程数量
		int threadNum = 5;
        //子线程的分片计算间隔
		int gap = A.length / threadNum;
		CountDownLatch countDownLatch = new CountDownLatch(threadNum);
		
		// 并行计算
		startTime = System.currentTimeMillis();
		for (int i = 0; i < threadNum; i++) {
			MatrixMulti matrixMulti = new MatrixMulti(A, B, i, gap, parallel_result, countDownLatch);
			matrixMulti.start();
		}
		countDownLatch.await();
		endTime = System.currentTimeMillis();
		System.out.println("并行计算开始时刻:" + (startTime));
		System.out.println("并行计算结束时刻:" + (endTime));
		System.out.println("并行计算运行时间:" + (endTime - startTime));
 
		// 串行计算
		startTime = System.currentTimeMillis();
		for (int i = 0; i < A.length; i++) {
			for (int j = 0; j < B[0].length; j++) {
				for (int k = 0; k < A[0].length; k++)
					serial_result[i][j] += A[i][k] * B[k][j];
			}
		}
		endTime = System.currentTimeMillis();
		System.out.println("串行计算开始时刻:" + (startTime));
		System.out.println("串行计算结束时刻:" + (endTime));
		System.out.println("串行计算运行时间:" + (endTime - startTime));
		
		
//		System.out.println(a.equals(b));
//		print(parallel_result);
//		System.out.println();
//		print(serial_result);
//		

		boolean isEqual = diffDoubleSecondArr(parallel_result, serial_result);
		System.out.println("are they equal?" +isEqual);
	}
}



